﻿namespace UnityEditor
{
    using System;
    using System.Runtime.InteropServices;
    using UnityEditorInternal;
    using UnityEngine;

    [CanEditMultipleObjects, CustomEditor(typeof(Camera))]
    internal class CameraEditor : Editor
    {
        private static readonly Color kGizmoCamera = new Color(0.9137255f, 0.9137255f, 0.9137255f, 0.5019608f);
        private const float kPreviewNormalizedSize = 0.2f;
        private const float kPreviewWindowOffset = 10f;
        private readonly AnimValueManager m_Anims = new AnimValueManager();
        private SerializedProperty m_BackgroundColor;
        private SerializedProperty m_ClearFlags;
        private SerializedProperty m_CullingMask;
        private SerializedProperty m_Depth;
        private SerializedProperty m_FarClip;
        private SerializedProperty m_FieldOfView;
        private SerializedProperty m_HDR;
        private SerializedProperty m_NearClip;
        private GUIContent[] m_NearFarClipPlaneLabels = new GUIContent[] { new GUIContent("Near"), new GUIContent("Far") };
        private SerializedProperty m_NormalizedViewPortRect;
        private SerializedProperty m_Orthographic;
        private SerializedProperty m_OrthographicSize;
        private Camera m_PreviewCamera;
        private SerializedProperty m_RenderingPath;
        private readonly AnimBool m_ShowBGColorOptions = new AnimBool();
        private readonly AnimBool m_ShowDeferredWarning = new AnimBool();
        private readonly AnimBool m_ShowOrthoOptions = new AnimBool();
        private SerializedProperty m_TargetTexture;

        private static void GetFrustrum(Camera camera, Vector3[] near, Vector3[] far, out float aspectGameView)
        {
            aspectGameView = GetGameViewAspectRatio(camera);
            Rect rect = camera.rect;
            if ((rect.width >= 0f) && (rect.height >= 0f))
            {
                float orthographicSize;
                float num2;
                float num3;
                float num4;
                float num5;
                float num6;
                if (!camera.isOrthoGraphic)
                {
                    orthographicSize = Mathf.Tan((camera.fov * 0.01745329f) * 0.5f);
                    num2 = orthographicSize * aspectGameView;
                    orthographicSize *= rect.height;
                    num2 *= rect.width;
                    num3 = num2 * camera.far;
                    num5 = orthographicSize * camera.far;
                    num4 = num2 * camera.near;
                    num6 = orthographicSize * camera.near;
                }
                else
                {
                    orthographicSize = camera.orthographicSize;
                    num2 = orthographicSize * aspectGameView;
                    orthographicSize *= rect.height;
                    num2 *= rect.width;
                    num3 = num2;
                    num5 = orthographicSize;
                    num4 = num2;
                    num6 = orthographicSize;
                }
                Matrix4x4 matrixx = Matrix4x4.TRS(camera.transform.position, camera.transform.rotation, Vector3.one);
                if (far != null)
                {
                    far[0] = new Vector3(-num3, -num5, camera.far);
                    far[1] = new Vector3(-num3, num5, camera.far);
                    far[2] = new Vector3(num3, num5, camera.far);
                    far[3] = new Vector3(num3, -num5, camera.far);
                    for (int i = 0; i < 4; i++)
                    {
                        far[i] = matrixx.MultiplyPoint(far[i]);
                    }
                }
                if (near != null)
                {
                    near[0] = new Vector3(-num4, -num6, camera.near);
                    near[1] = new Vector3(-num4, num6, camera.near);
                    near[2] = new Vector3(num4, num6, camera.near);
                    near[3] = new Vector3(num4, -num6, camera.near);
                    for (int j = 0; j < 4; j++)
                    {
                        near[j] = matrixx.MultiplyPoint(near[j]);
                    }
                }
            }
        }

        private static float GetGameViewAspectRatio(Camera fallbackCamera)
        {
            Vector2 sizeOfMainGameView = GameView.GetSizeOfMainGameView();
            if (sizeOfMainGameView.x < 0f)
            {
                sizeOfMainGameView.x = fallbackCamera.GetScreenWidth();
                sizeOfMainGameView.y = fallbackCamera.GetScreenHeight();
            }
            return (sizeOfMainGameView.x / sizeOfMainGameView.y);
        }

        private static Vector3 MidPointPositionSlider(Vector3 position1, Vector3 position2, Vector3 direction)
        {
            Vector3 position = Vector3.Lerp(position1, position2, 0.5f);
            return Handles.Slider(position, direction, HandleUtility.GetHandleSize(position) * 0.03f, new Handles.DrawCapFunction(Handles.DotCap), 0f);
        }

        public void OnEnable()
        {
            this.m_ClearFlags = base.serializedObject.FindProperty("m_ClearFlags");
            this.m_BackgroundColor = base.serializedObject.FindProperty("m_BackGroundColor");
            this.m_NormalizedViewPortRect = base.serializedObject.FindProperty("m_NormalizedViewPortRect");
            this.m_NearClip = base.serializedObject.FindProperty("near clip plane");
            this.m_FieldOfView = base.serializedObject.FindProperty("field of view");
            this.m_Orthographic = base.serializedObject.FindProperty("orthographic");
            this.m_OrthographicSize = base.serializedObject.FindProperty("orthographic size");
            this.m_Depth = base.serializedObject.FindProperty("m_Depth");
            this.m_CullingMask = base.serializedObject.FindProperty("m_CullingMask");
            this.m_RenderingPath = base.serializedObject.FindProperty("m_RenderingPath");
            this.m_TargetTexture = base.serializedObject.FindProperty("m_TargetTexture");
            this.m_HDR = base.serializedObject.FindProperty("m_HDR");
            Camera target = (Camera) base.target;
            this.m_ShowBGColorOptions.value = !this.m_ClearFlags.hasMultipleDifferentValues && ((target.clearFlags == CameraClearFlags.Color) || (target.clearFlags == CameraClearFlags.Skybox));
            this.m_ShowOrthoOptions.value = target.orthographic;
            this.m_ShowDeferredWarning.value = this.deferredWarningValue;
            this.m_Anims.Add(this.m_ShowBGColorOptions);
            this.m_Anims.Add(this.m_ShowOrthoOptions);
            this.m_Anims.Add(this.m_ShowDeferredWarning);
        }

        public override void OnInspectorGUI()
        {
            if (this.m_Anims.callback == null)
            {
                this.m_Anims.callback = new AnimValueManager.Callback(this.Repaint);
            }
            base.serializedObject.Update();
            Camera target = (Camera) base.target;
            this.m_ShowBGColorOptions.target = !this.m_ClearFlags.hasMultipleDifferentValues && ((target.clearFlags == CameraClearFlags.Color) || (target.clearFlags == CameraClearFlags.Skybox));
            this.m_ShowOrthoOptions.target = !this.m_Orthographic.hasMultipleDifferentValues && target.orthographic;
            this.m_ShowDeferredWarning.target = this.deferredWarningValue;
            EditorGUILayout.PropertyField(this.m_ClearFlags, new GUILayoutOption[0]);
            if (EditorGUILayout.BeginFadeGroup(this.m_ShowBGColorOptions.faded))
            {
                EditorGUILayout.PropertyField(this.m_BackgroundColor, new GUIContent("Background", "Camera clears the screen to this color before rendering."), new GUILayoutOption[0]);
            }
            EditorGUILayout.EndFadeGroup();
            EditorGUILayout.PropertyField(this.m_CullingMask, new GUILayoutOption[0]);
            EditorGUILayout.Space();
            ProjectionType selected = !this.m_Orthographic.boolValue ? ProjectionType.Perspective : ProjectionType.Orthographic;
            EditorGUI.BeginChangeCheck();
            EditorGUI.showMixedValue = this.m_Orthographic.hasMultipleDifferentValues;
            selected = (ProjectionType) EditorGUILayout.EnumPopup("Projection", selected, new GUILayoutOption[0]);
            EditorGUI.showMixedValue = false;
            if (EditorGUI.EndChangeCheck())
            {
                this.m_Orthographic.boolValue = selected == ProjectionType.Orthographic;
            }
            if (!this.m_Orthographic.hasMultipleDifferentValues)
            {
                if (EditorGUILayout.BeginFadeGroup(this.m_ShowOrthoOptions.faded))
                {
                    EditorGUILayout.PropertyField(this.m_OrthographicSize, new GUIContent("Size"), new GUILayoutOption[0]);
                }
                EditorGUILayout.EndFadeGroup();
                if (EditorGUILayout.BeginFadeGroup(1f - this.m_ShowOrthoOptions.faded))
                {
                    EditorGUILayout.Slider(this.m_FieldOfView, 1f, 179f, new GUIContent("Field of View"), new GUILayoutOption[0]);
                }
                EditorGUILayout.EndFadeGroup();
            }
            GUI.Label(GUILayoutUtility.GetRect(EditorGUILayout.kLabelFloatMinW, 16f, EditorStyles.numberField), "Clipping Planes", EditorStyles.label);
            EditorGUI.indentLevel++;
            EditorGUI.MultiField(GUILayoutUtility.GetRect(EditorGUILayout.kLabelFloatMinW, 16f, EditorStyles.numberField), this.m_NearFarClipPlaneLabels, this.m_NearClip.Copy());
            EditorGUI.indentLevel--;
            EditorGUILayout.PropertyField(this.m_NormalizedViewPortRect, new GUILayoutOption[0]);
            EditorGUILayout.Space();
            EditorGUILayout.PropertyField(this.m_Depth, new GUILayoutOption[0]);
            EditorGUILayout.PropertyField(this.m_RenderingPath, new GUILayoutOption[0]);
            if (EditorGUILayout.BeginFadeGroup(this.m_ShowDeferredWarning.faded))
            {
                EditorGUILayout.HelpBox(EditorGUIUtility.TextContent("CameraEditor.DeferredProOnly").text, MessageType.Warning, false);
            }
            EditorGUILayout.EndFadeGroup();
            EditorGUILayout.PropertyField(this.m_TargetTexture, new GUILayoutOption[0]);
            EditorGUILayout.PropertyField(this.m_HDR, new GUILayoutOption[0]);
            base.serializedObject.ApplyModifiedProperties();
        }

        public void OnOverlayGUI(UnityEngine.Object target, SceneView sceneView)
        {
            if (target != null)
            {
                Camera other = (Camera) target;
                Vector2 sizeOfMainGameView = GameView.GetSizeOfMainGameView();
                if (sizeOfMainGameView.x < 0f)
                {
                    sizeOfMainGameView.x = sceneView.position.width;
                    sizeOfMainGameView.y = sceneView.position.height;
                }
                Rect rect = other.rect;
                sizeOfMainGameView.x *= Mathf.Max(rect.width, 0f);
                sizeOfMainGameView.y *= Mathf.Max(rect.height, 0f);
                if ((sizeOfMainGameView.x > 0f) && (sizeOfMainGameView.y > 0f))
                {
                    float num = sizeOfMainGameView.x / sizeOfMainGameView.y;
                    sizeOfMainGameView.y = 0.2f * sceneView.position.height;
                    sizeOfMainGameView.x = sizeOfMainGameView.y * num;
                    if (sizeOfMainGameView.y > (sceneView.position.height * 0.5f))
                    {
                        sizeOfMainGameView.y = sceneView.position.height * 0.5f;
                        sizeOfMainGameView.x = sizeOfMainGameView.y * num;
                    }
                    if (sizeOfMainGameView.x > (sceneView.position.width * 0.5f))
                    {
                        sizeOfMainGameView.x = sceneView.position.width * 0.5f;
                        sizeOfMainGameView.y = sizeOfMainGameView.x / num;
                    }
                    Rect rect2 = GUILayoutUtility.GetRect(sizeOfMainGameView.x, sizeOfMainGameView.y);
                    rect2.y = ((sceneView.position.height - rect2.y) - rect2.height) + 1f;
                    if (Event.current.type == EventType.Repaint)
                    {
                        this.previewCamera.CopyFrom(other);
                        this.previewCamera.targetTexture = null;
                        this.previewCamera.pixelRect = rect2;
                        this.previewCamera.Render();
                    }
                }
            }
        }

        public void OnSceneGUI()
        {
            Camera target = (Camera) base.target;
            Rect rect = target.rect;
            if (((Mathf.Abs(rect.x) <= 1f) && (Mathf.Abs(rect.y) <= 1f)) && ((rect.width > 0f) && (rect.height > 0f)))
            {
                float num;
                SceneViewOverlay.Window(new GUIContent("Camera Preview"), new SceneViewOverlay.WindowFunction(this.OnOverlayGUI), -100, base.target, SceneViewOverlay.WindowDisplayOption.OneWindowPerTarget);
                Color color = Handles.color;
                Color kGizmoCamera = CameraEditor.kGizmoCamera;
                kGizmoCamera.a *= 2f;
                Handles.color = kGizmoCamera;
                Vector3[] far = new Vector3[4];
                GetFrustrum(target, null, far, out num);
                Vector3 from = far[0];
                Vector3 vector2 = far[1];
                Vector3 to = far[2];
                Vector3 vector4 = far[3];
                bool changed = GUI.changed;
                Undo.SetSnapshotTarget(target, "Adjust Camera");
                Vector3 vector5 = Vector3.Lerp(from, to, 0.5f);
                float num2 = -1f;
                Vector3 vector6 = MidPointPositionSlider(vector2, to, target.transform.up);
                if (!GUI.changed)
                {
                    vector6 = MidPointPositionSlider(from, vector4, -target.transform.up);
                }
                if (GUI.changed)
                {
                    Vector3 vector8 = vector6 - vector5;
                    num2 = vector8.magnitude / rect.height;
                }
                GUI.changed = false;
                vector6 = MidPointPositionSlider(vector4, to, target.transform.right);
                if (!GUI.changed)
                {
                    vector6 = MidPointPositionSlider(from, vector2, -target.transform.right);
                }
                if (GUI.changed)
                {
                    Vector3 vector9 = vector6 - vector5;
                    num2 = (vector9.magnitude / rect.width) / num;
                }
                if (num2 >= 0f)
                {
                    if (target.orthographic)
                    {
                        target.orthographicSize = num2;
                    }
                    else
                    {
                        Vector3 vector7 = vector5 + ((Vector3) (target.transform.up * num2));
                        target.fieldOfView = Vector3.Angle(target.transform.forward, vector7 - target.transform.position) * 2f;
                    }
                    changed = true;
                }
                GUI.changed = changed;
                Handles.color = color;
            }
        }

        private static void RenderGizmo(Camera camera)
        {
            float num;
            Vector3[] near = new Vector3[4];
            Vector3[] far = new Vector3[4];
            GetFrustrum(camera, near, far, out num);
            Color color = Handles.color;
            Handles.color = kGizmoCamera;
            for (int i = 0; i < 4; i++)
            {
                Handles.DrawLine(near[i], near[(i + 1) % 4]);
                Handles.DrawLine(far[i], far[(i + 1) % 4]);
                Handles.DrawLine(near[i], far[i]);
            }
            Handles.color = color;
        }

        private Camera camera
        {
            get
            {
                return (base.target as Camera);
            }
        }

        private bool deferredWarningValue
        {
            get
            {
                return (!InternalEditorUtility.HasPro() && ((this.camera.renderingPath == RenderingPath.DeferredLighting) || ((PlayerSettings.renderingPath == RenderingPath.DeferredLighting) && (this.camera.renderingPath == RenderingPath.UsePlayerSettings))));
            }
        }

        private Camera previewCamera
        {
            get
            {
                if (this.m_PreviewCamera == null)
                {
                    System.Type[] components = new System.Type[] { typeof(Camera) };
                    this.m_PreviewCamera = EditorUtility.CreateGameObjectWithHideFlags("Preview Camera", HideFlags.HideAndDontSave, components).GetComponent<Camera>();
                }
                this.m_PreviewCamera.enabled = false;
                return this.m_PreviewCamera;
            }
        }

        private enum ProjectionType
        {
            Perspective,
            Orthographic
        }
    }
}

